home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_11_01
/
1101083a
< prev
next >
Wrap
Text File
|
1992-11-08
|
12KB
|
487 lines
//////////////
// Isam.cpp //
//////////////
#include "isam.h"
#include <fstream.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
static struct BTParms {
char name[9], filename[9];
int keylen, dreclen, maxrecs, indxfd, datafd,
kstart, count;
t_func keygen;
} btparms[40];
static int items = 0;
extern "C" {
int (*Write)(int,const void *,unsigned) = write;
int (*Read )(int,void *,unsigned) = read;
}
static void isam_init(void);
static void isam_init(void)
{
ifstream btr("btparms.btr");
char nwln, item[81], buf[20], fname[13], fcname[9];
int i;
if (!btr)
eprintf("\n\nUnable to open btparms.btr.\n");
for (i = 0; i < 40; i++) {
btr.get (item, 80);
if (!strlen(item))
break;
btr.get(nwln);
strcpy(btparms[i].name, strtok(item, "^"));
strtok(NULL, "^");
strcpy(buf, strtok(NULL, "^"));
btparms[i].keylen = atoi(buf);
strtok(NULL, "^");
strcpy(buf, strtok(NULL, "^"));
btparms[i].dreclen = atoi(buf);
strtok(NULL, "^");
strcpy(fname, strtok(NULL, "^"));
strtok(NULL, "^");
strcpy(buf, strtok(NULL, "^"));
btparms[i].kstart = atoi(buf);
strcpy(fcname, nospace(strtok(NULL, "^")));
strcpy(btparms[i].filename, strtok(fname,"."));
btparms[i].count = 0;
btparms[i].indxfd = btparms[i].datafd = -1;
if (strlen(fcname))
btparms[i].keygen = cataloged_func (
catalog_number(fcname));
else
btparms[i].keygen = (t_func) NULL;
}
items = i;
btr.close();
if (!items)
eprintf("\n\nUnable to initialize isam system.\n");
for (i = items; i < 40; i++) {
strcpy(btparms[i].name,"");
strcpy(btparms[i].filename,"");
btparms[i].keygen = NULL;
btparms[i].keylen = btparms[i].dreclen =
btparms[i].count = btparms[i].kstart = 0;
btparms[i].indxfd = btparms[i].datafd = -1;
}
}
Isam::Isam(const char *datafilename, int e)
{
int i, j;
char buf[20];
backingout = 0;
elements = e;
if (!items) // this is the first Isam
isam_init(); // initialize btparms
strcpy(buf, nospace(datafilename));
indices = 0;
// find btree params
for (i = 0; i < items; i++)
if (!stricmp(buf, btparms[i].filename))
btr[indices++] = i;
if (!indices) // couldn't find any, fatal
eprintf("\n\nCan't find parameters for %s!\n",
datafilename);
// set up btree interfaces
if( !(btc = new BTC [indices]) ||
!(inames = new char* [indices]) ||
!(loc = new long [elements]) ||
!(oldrec = new char* [elements]) ||
!(rec = new char* [elements]) ||
!(okey = new char [btparms[*btr].dreclen])||
!(nkey = new char [btparms[*btr].dreclen]) )
eprintf("\n\nOut of memory.\n");
for (i = 0; i < indices; i++) {
inames[i] = btparms[btr[i]].name;
btc[i].btvcount = 1;
if (btrinit(inames[i], btc+i) == ERR)
eprintf("\n\nCouldn't initialize %s.\n",
inames[i]);
btc[i].btmulti = 0; // record locking off
}
for (i = 0; i < elements; i++) {
loc[i] = 0L;
if (!(oldrec[i] = new char
[btparms[*btr].dreclen + 1]) ||
!(rec[i] = new char
[btparms[*btr].dreclen + 1]) )
eprintf("\n\nOut of memory.\n");
}
if (btparms[*btr].count) { // open files if neccesary
fd[0] = btparms[*btr].datafd;
fd[1] = btparms[*btr].indxfd;
}
else { // yup, it's neccesary
strcpy(buf, btparms[*btr].filename);
strcat(buf, ".dat");
if ((fd[0]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
eprintf("\n\nCan't open %s.\n", buf);
strcpy(buf, btparms[*btr].filename);
strcat(buf, ".idx");
if ((fd[1]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
eprintf("\n\nCan't open %s.\n", buf);
btparms[*btr].datafd = fd[0];
btparms[*btr].indxfd = fd[1];
}
(btparms[*btr].count)++; // record that we are here
clear();
}
Isam::~Isam()
{
int i, j;
// clean up out mess
for (i = 0; i < indices; i++)
btrterm(btc+i);
for (i = 0; i < elements; i++) {
delete [] oldrec[i];
delete [] rec[i];
}
delete [] btc;
delete [] inames;
delete [] loc;
delete [] oldrec;
delete [] rec;
delete [] nkey;
delete [] okey;
// if we're last ones out, turn off the lights
if (!(--(btparms[*btr].count))) {
close (fd[0]);
close (fd[1]);
btparms[*btr].indxfd = -1;
btparms[*btr].datafd = -1;
}
}
int Isam::write ()
{
int deltakey, old1, new1, ele, index, result, len,
start, notfirst;
t_func fcn;
if (*loc < 0) // programmer hasn't followed rules
eprintf ("No writes after gets!");
for (ele = 0; ele < elements; ele++) {
old1 = strlen(oldrec[ele]);
new1 = strlen( rec[ele]);
if (!(old1 || new1) ||
!strcmp(oldrec[ele], rec[ele]))
continue;
for (index = 0; index < indices; index++) {
// generate the old and/or new key
len = btparms[btr[index]].keylen;
start = btparms[btr[index]].kstart;
if ((fcn = btparms[btr[index]].keygen) !=
(t_func) NULL) {
if (old1)
strcpy(okey, fcn(oldrec[ele]));
if (new1)
strcpy(nkey, fcn( rec[ele]));
}
else {
if (old1)
strnncpy(okey, oldrec[ele] + start, len);
if (new1)
strnncpy(nkey, rec[ele] + start, len);
}
deltakey = (!old1||!new1||stricmp(okey,nkey));
if (old1 && deltakey) {
notfirst = 0;
while (strlen(okey) >= len) {
strnncpy(btc[index].btkey, ToUpper(okey),
len);
btc[index].btoptype = (new1 || index ||
notfirst++ || backingout) ? DELTKY
: DELETE;
btc[index].btloc = loc[ele];
result=cbtree(fd[0], fd[1], btc+index);
if (result != BTCALLOK)
backout (ele, 'D', index, result);
strcpy(okey, okey + len);
}
}
if (new1 && deltakey) {
notfirst = 0;
while (strlen(nkey) >= len) {
strnncpy(btc[index].btkey, ToUpper(nkey),
len);
btc[index].btoptype = (loc[ele] == 0L) ?
INSERT : ISRTKY;
btc[index].btloc = loc[ele];
result = cbtree(fd[0], fd[1], btc+index);
if (result == BTCALLOK)
loc[ele] = btc[index].btloc;
else
backout(ele, 'I', index, result);
strcpy(nkey, nkey + len);
}
}
}
if (!new1)
continue;
if (btseek (fd[0], loc[ele], btc->btdtalen)
== -1L)
backout(ele, 'S');
if (Write(fd[0],rec[ele],(unsigned)btc->btdtalen)
!= btc->btdtalen)
backout(ele, 'W');
}
clear ();
return 0;
}
void Isam::backout(int ele,char op,int index,int result)
{ // backs out record add/change/delete on error
char *trec;
if (!(trec = new char [btparms[*btr].dreclen]) ||
backingout) // I quit! Error in error backout!
eprintf("\n\nBackout error, error type was %c\n",
backingout);
if (index >= 0)
indices = index + 1; // those beyond index are ok
backingout = op;
elements = 1;
strcpy(trec,rec[ele]);
strcpy(rec[0],oldrec[ele]);
strcpy(oldrec[0],trec);
loc[0] = loc[ele];
write();
switch (backingout) {
case 'I':
eprintf(
"\n\nINSERT error, element %d, index %s, result %d\n",
ele, inames[index], result);
case 'D':
eprintf(
"\n\nDELETE error, element %d, index %s, result %d\n",
ele, inames[index], result);
case 'S':
eprintf ("\n\nSeek error, element %d\n", ele);
case 'W':
eprintf ("\n\nWrite error, element %d\n", ele);
}
}
int Isam::read(const char *key, int ele_limit, int idx,
int ele)
{
int i = 0, j = 0;
if ((ele_limit + ele) > elements)
eprintf("\n\nNot enough elements!\n");
free_svkey(btc+idx);
btc[idx].btoptype = GETALL;
strcpy(btc[idx].btkey, ToUpper(key));
btc[idx].btloc = 0L;
while (cbtree(fd[0], fd[1], btc + idx) == BTCALLOK) {
while (btc[idx].btrecnum[i-j] != 0L) {
if (i < ele_limit) {
loc[i+ele] = btc[idx].btrecnum[i-j];
btseek(fd[0], loc[i+ele], btc[idx].btdtalen);
Read (fd[0], rec[i+ele], btc[idx].btdtalen);
}
i++;
if (!((i-j) < btc[idx].btmax))
break;
}
if ((i-j) < btc[idx].btmax)
break;
j += btc[idx].btmax;
}
for (j = 0; j < ele_limit; j++)
strcpy(oldrec[j], rec[j]);
return i;
}
int Isam::getfirst(int index)
{
return getxxx (inde